package com.zxjbyte.yiyi.module.system.manager;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zxjbyte.yiyi.framework.common.constant.StatusConstant;
import com.zxjbyte.yiyi.framework.common.exception.ServiceException;
import com.zxjbyte.yiyi.framework.common.util.AuthUtil;
import com.zxjbyte.yiyi.framework.common.util.CollXUtil;
import com.zxjbyte.yiyi.module.system.domain.entity.DictDataPO;
import com.zxjbyte.yiyi.module.system.domain.entity.DictTypePO;
import com.zxjbyte.yiyi.module.system.domain.request.dict.DictDataAddRequest;
import com.zxjbyte.yiyi.module.system.domain.request.dict.DictDataUpdateRequest;
import com.zxjbyte.yiyi.module.system.domain.request.dict.DictTypeUpdateRequest;
import com.zxjbyte.yiyi.module.system.service.dict.IDictDataService;
import com.zxjbyte.yiyi.module.system.service.dict.IDictTypeService;
import com.zxjbyte.yiyi.module.system.util.DictCacheUtil;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 字典管理器
 *
 * @Author zhangxingjia
 * @Date 2024/2/23 17:59
 * @Version: 1.0
 */
@Component
public class DictManager {

    @Resource
    private IDictDataService dictDataService;
    @Resource
    private IDictTypeService dictTypeService;

    /**
     * 删除字典数据
     * @param id
     */
    public void dictDataDelete(Long id) {
        DictDataPO dictDataPo = dictDataService.getById(id);
        if(Objects.isNull(dictDataPo)){
            throw new ServiceException("字典数据不存在");
        }
        dictDataService.update(Wrappers.<DictDataPO>lambdaUpdate()
                .set(DictDataPO::getUpdateTime, new Date())
                .set(DictDataPO::getUpdateUser, AuthUtil.getUsername())
                .set(DictDataPO::getDeleted, true)
                .eq(DictDataPO::getId, id)
        );
        // 更新缓存
        initDictDateCache(dictDataPo.getDictType());
    }

    /**
     * 字段数据新增
     * @param request
     */
    public void dictDataAdd(DictDataAddRequest request) {
        if(dictTypeService.count(Wrappers.<DictTypePO>lambdaQuery().eq(DictTypePO::getType, request.getDictType())) <= 0){
            throw new ServiceException("字典类型未定义");
        }
        DictDataPO entity = new DictDataPO();
        entity.setDictType(request.getDictType());
        entity.setSort(request.getSort());
        entity.setDictLabel(request.getDictLabel());
        entity.setDictValue(request.getDictValue());
        entity.setCssClass(request.getCssClass());
        entity.setShowStyle(request.getShowStyle());
        entity.setStatus(request.getStatus());
        entity.setRemark(request.getRemark());
        Date now = new Date();
        String username = AuthUtil.getUsername();
        entity.setCreateTime(now);
        entity.setCreateUser(username);
        entity.setUpdateTime(now);
        entity.setUpdateUser(username);
        dictDataService.save(entity);
        // 更新缓存
        initDictDateCache(request.getDictType());
    }

    /**
     * 数据字典编辑
     * @param request
     */
    public void dictDataUpdate(DictDataUpdateRequest request){
        DictDataPO entity = dictDataService.getById(request.getId());
        if(Objects.isNull(entity)){
            throw new ServiceException("数据字典不存在！");
        }
        dictDataService.lambdaUpdate().set(DictDataPO::getDictLabel, request.getDictLabel())
                .set(DictDataPO::getDictValue, request.getDictValue())
                .set(DictDataPO::getSort, request.getSort())
                .set(DictDataPO::getCssClass, request.getCssClass())
                .set(DictDataPO::getShowStyle, request.getShowStyle())
                .set(DictDataPO::getStatus, request.getStatus())
                .set(DictDataPO::getRemark, StrUtil.blankToDefault(request.getRemark(), StrUtil.EMPTY))
                .set(DictDataPO::getUpdateUser, AuthUtil.getUsername())
                .set(DictDataPO::getUpdateTime, new Date())
                .eq(DictDataPO::getId, request.getId()).update();
        // 更新缓存
        initDictDateCache(entity.getDictType());
    }

    /**
     * 字典类型编辑
     *
     * @param request
     */
    @Transactional(rollbackFor = Exception.class)
    public void dictTypeUpdate(DictTypeUpdateRequest request) {
        DictTypePO dictTypePo = dictTypeService.getById(request.getId());
        if(Objects.isNull(dictTypePo)){
            throw new ServiceException("当前字典类型不存在");
        }
        String oldType = dictTypePo.getType();
        boolean typeChange = !Objects.equals(oldType, request.getType());
        if(typeChange){
            if(dictTypeService.count(Wrappers.<DictTypePO>lambdaQuery().eq(DictTypePO::getType, request.getType())) > 0){
                throw new ServiceException("字典类型已存在");
            }
        }
        Date now = new Date();
        dictTypeService.lambdaUpdate().set(DictTypePO::getType, request.getType())
                .set(DictTypePO::getName, StrUtil.blankToDefault(request.getName(), StrUtil.EMPTY))
                .set(DictTypePO::getRemark, StrUtil.blankToDefault(request.getRemark(), StrUtil.EMPTY))
                .set(DictTypePO::getStatus, request.getStatus())
                .set(DictTypePO::getUpdateTime, now)
                .set(DictTypePO::getUpdateUser, AuthUtil.getUsername())
                .eq(DictTypePO::getId, request.getId()).update();
        if(typeChange){
            // 更新字典数据类型
            dictDataService.lambdaUpdate().set(DictDataPO::getDictType, request.getType())
                    .set(DictDataPO::getUpdateTime, now)
                    .set(DictDataPO::getUpdateUser, AuthUtil.getUsername())
                    .eq(DictDataPO::getDictType, oldType).update();
            DictCacheUtil.removeDict(oldType);
            if(Objects.equals(request.getStatus(), StatusConstant.ENABLE)){
                List<DictDataPO> dictDataList = dictDataService.lambdaQuery().eq(DictDataPO::getDictType, request.getType()).list();
                if(CollXUtil.isNotEmpty(dictDataList)){
                    DictCacheUtil.setDict(request.getType(), dictDataList);
                }
            }
        } else {
            // 字典类型禁用，移除缓存
            if(Objects.equals(request.getStatus(), StatusConstant.DISABLE)){
                DictCacheUtil.removeDict(oldType);
            }
        }
    }

    /**
     * 字典类型删除
     *
     * @param id
     */
    public void dictTypeDelete(Long id) {
        DictTypePO dictTypePo = dictTypeService.getById(id);
        if(Objects.isNull(dictTypePo)){
            throw new ServiceException("当前字典类型不存在");
        }
        if(dictDataService.count(Wrappers.<DictDataPO>lambdaQuery().eq(DictDataPO::getDictType, dictTypePo.getType())) > 0){
            throw new ServiceException("当前字典类型下存在字典数据，不可删除！");
        }
        dictTypeService.update(Wrappers.<DictTypePO>lambdaUpdate()
                .set(DictTypePO::getUpdateTime, new Date())
                .set(DictTypePO::getUpdateUser, AuthUtil.getUsername())
                .set(DictTypePO::getDeleted, true)
                .eq(DictTypePO::getId, id)
        );
        DictCacheUtil.removeDict(dictTypePo.getType());
    }

    /**
     * 查询初始化字典数据缓存
     * @param dictType
     */
    private void initDictDateCache(String dictType){
        // 更新缓存
        List<DictDataPO> list = dictDataService.lambdaQuery().eq(DictDataPO::getDictType, dictType).list();
        DictCacheUtil.setDict(dictType, list);
    }
}
